package com.alibaba.ttl.threadpool;

import cn.micro.ttl.mdc.MDCThreadWrap;
import com.alibaba.ttl.TtlCallable;
import com.alibaba.ttl.TtlRunnable;
import com.alibaba.ttl.spi.TtlEnhanced;
import com.alibaba.ttl.spi.TtlWrapper;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

public class ExecutorServiceTtlMDCWrapper implements ExecutorService, TtlWrapper<ExecutorService>, TtlEnhanced {

    private final ExecutorService executorService;
    protected final boolean idempotent;

    public ExecutorServiceTtlMDCWrapper(ExecutorService executorService, boolean idempotent) {
        this.executorService = executorService;
        this.idempotent = idempotent;
    }

    @Override
    public void execute(Runnable command) {
        executorService.execute(TtlRunnable.get(MDCThreadWrap.runnable(command), false, idempotent));
    }

    @Override
    public ExecutorService unwrap() {
        return executorService;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ExecutorServiceTtlMDCWrapper that = (ExecutorServiceTtlMDCWrapper) o;

        return executorService.equals(that.executorService);
    }

    @Override
    public int hashCode() {
        return executorService.hashCode();
    }

    @Override
    public String toString() {
        return this.getClass().getName() + " - " + executorService.toString();
    }

    @Override
    public void shutdown() {
        executorService.shutdown();
    }

    @Override
    public List<Runnable> shutdownNow() {
        return executorService.shutdownNow();
    }

    @Override
    public boolean isShutdown() {
        return executorService.isShutdown();
    }

    @Override
    public boolean isTerminated() {
        return executorService.isTerminated();
    }

    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return executorService.awaitTermination(timeout, unit);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return executorService.submit(TtlCallable.get(MDCThreadWrap.callable(task), false, idempotent));
    }

    @Override
    public <T> Future<T> submit(Runnable task, T result) {
        return executorService.submit(TtlRunnable.get(MDCThreadWrap.runnable(task), false, idempotent), result);
    }

    @Override
    public Future<?> submit(Runnable task) {
        return executorService.submit(TtlRunnable.get(MDCThreadWrap.runnable(task), false, idempotent));

    }

    @Override
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
        return executorService.invokeAll(tasks);
    }

    @Override
    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
        return executorService.invokeAll(tasks, timeout, unit);
    }

    @Override
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
        return executorService.invokeAny(tasks);
    }

    @Override
    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        return executorService.invokeAny(tasks, timeout, unit);
    }
}
